function moveWithTransition(element, targetObj, duration) {
    element.style.transition = `all ${duration / 1000 + "s"} linear`;
    for (var attr in targetObj) {
        element.style[attr] = targetObj[attr];
    }
    setTimeout(() => {
        element.style.transition = "none";
    }, duration);
}

/* 从样式属性值中截取单位 */
function getUnit(value) {
    var digits = "0123456789.+-";
    value = value + ""; //200px
    for (var i = 0; i < value.length; i++) {
        var char = value[i];
        if (digits.includes(char) === false) {
            return value.slice(i);
        }
    }
    return "";
}

/**
 * 多属性动画
 * @param {Element} element 要做动画的元素
 * @param {Object} targetObj 属性目标值的对象 封装了所有要做动画的属性及其目标值
 * @param {number} timeCost 动画耗时，单位毫秒
 * @param {Function} callback 动画结束的回调函数
 * animate(box,{left:"200px",top:"500px",opacity:0.5},3000,()=>console.log("动画结束"))
 */
function animate(element, targetObj, timeCost = 1000, callback = null) {
    var MILLIS_PER_FRAME = 50;

    // 计算出帧数
    var totalFrames = Math.floor(timeCost / MILLIS_PER_FRAME);

    /* 计算各属性的动画速度 */
    // 动画速度 = （目标值-起始值）/ 帧数
    // targetObj {left:"200px",top:"500px",opacity:0.5}
    /* 
            speedObj
            {            
                "left":{
                    "speed":5,
                    "start":0,
                    "unit":"px"
                },
                "top":{
                    "speed":5,
                    "start":0,
                    "unit":"px"
                },
                "opacity":{
                    "speed":-0.0225,
                    "start":1,
                    "unit":""
                }
            }
            */
    var speedObj = {};

    /* 
            遍历所有的目标属性 
            遍历的过程中,key依次为:left top opacity 
            */
    for (let key in targetObj) {
        /* 求出动画速度（每帧的偏移量） */
        var targetValue = parseFloat(targetObj[key]); //取出目标值
        var startValue = parseFloat(window.getComputedStyle(element)[key]); //获取起始值
        var speed = (targetValue - startValue) / totalFrames; //计算动画速度（每帧的偏移量）

        speedObj[key] = {
            speed: speed,
            start: startValue,
            unit: getUnit(targetObj[key]),
        };
    }
    console.log(JSON.stringify(speedObj));

    // 实时统计帧数
    var frame = 0;

    // 动画定时器
    var timer = null;

    /* 启动动画定时器 */
    timer = window.setInterval(
        /* 每帧回调一次任务函数 */
        function () {
            frame++;

            // 每帧 各属性 都按动画速度进行偏移
            for (let key in speedObj) {
                // 当前位置 = 起始位置 + 动画速度*当前帧数 +单位
                element.style[key] =
                    speedObj[key].start +
                    speedObj[key].speed * frame +
                    speedObj[key].unit;
            }

            // 帧数一旦到位就停止定时器
            if (frame >= totalFrames) {
                window.clearInterval(timer);

                // 暴力校正到目标位置
                for (let key in targetObj) {
                    element.style[key] = targetObj[key];
                }

                // 如有有回调则调用之
                callback && callback();
            }
        },

        // 50毫秒一帧
        MILLIS_PER_FRAME
    );
}
